package com.hsc.base;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;

public class FeatureTreeRelation<T extends FeatureTree> {

    Map<String, Set<String>> id2ChildrenIdsMap;
    Map<String, String> id2pidMap;

    
    private boolean existPid(String pid) {
        return StringUtils.isNotEmpty(pid);
    }

    public FeatureTreeRelation() {
        this.id2ChildrenIdsMap = new HashMap<>();
        this.id2pidMap = new HashMap<>();
    }

    public FeatureTreeRelation(Collection<T> totalData) {
        this();
        if (!CollectionUtils.isEmpty(totalData)) {
            totalData.forEach(row -> {
                Set<String> childrenIds = this.id2ChildrenIdsMap.get(row.getPid());
                if (childrenIds == null) {
                    childrenIds = new HashSet<>();
                    this.id2ChildrenIdsMap.put(row.getPid(), childrenIds);
                }
                childrenIds.add(row.getId());
                this.id2pidMap.put(row.getId(), row.getPid());
            });
        }
    }


    /**
     * 获取后代节点。
     *
     * @param idList
     * @param includeSelf
     * @return
     */
    public Set<String> getDescendants(Collection<String> idList, boolean includeSelf) {
        Set<String> total = getDescendantsExcludeSelf(idList);
        if (includeSelf) {
            total.addAll(idList);
        }
        return total;
    }

    /**
     * 获取祖先节点。
     *
     * @param idList
     * @param includeSelf
     * @return
     */
    public Set<String> getAncestors(Collection<String> idList, boolean includeSelf) {
        Set<String> total = getAncestorsExcludeSelf(idList);
        if (includeSelf) {
            total.addAll(idList);
        }
        return total;
    }
    
    private Set<String> getDescendantsExcludeSelf(Collection<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return new HashSet<>();
        }
        Set<String> total = new HashSet<>();
        for (String id : idList) {
            Set<String> descendants = id2ChildrenIdsMap.get(id);
            if (!CollectionUtils.isEmpty(descendants)) {
                total.addAll(descendants);
                Set<String> descendantsIdList = new HashSet<>();
                descendants.forEach(item -> descendantsIdList.add(item));
                total.addAll(getDescendantsExcludeSelf(descendantsIdList));
            }
        }
        return total;
    }

    private Set<String> getAncestorsExcludeSelf(Collection<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return new HashSet<>();
        }
        Set<String> total = new HashSet<>();
        Set<String> pidList = new HashSet<>();
        for (String id : idList) {
            String pid = id2pidMap.get(id);
            if (existPid(pid)) {
                total.add(pid);
                pidList.add(pid);
            }
        }
        total.addAll(getAncestorsExcludeSelf(pidList));
        return total;
    }

    public Map<String, Set<String>> getId2ChildrenIdsMap() {
        return id2ChildrenIdsMap;
    }

    public void setId2ChildrenIdsMap(Map<String, Set<String>> id2ChildrenIdsMap) {
        this.id2ChildrenIdsMap = id2ChildrenIdsMap;
    }

    public Map<String, String> getId2pidMap() {
        return id2pidMap;
    }

    public void setId2pidMap(Map<String, String> id2pidMap) {
        this.id2pidMap = id2pidMap;
    }

//
//    public static class Tree implements FeatureTree {
//        private String id;
//        private String name;
//        private String pid;
//
//
//        public String getName() {
//            return name;
//        }
//
//        public void setName(String name) {
//            this.name = name;
//        }
//
//
//        @Override
//        public String getId() {
//            return id;
//        }
//
//        @Override
//        public void setId(String id) {
//            this.id = id;
//        }
//
//        @Override
//        public String getPid() {
//            return pid;
//        }
//
//        @Override
//        public void setPid(String pid) {
//            this.pid = pid;
//        }
//
//
//        public Tree(String id, String name, String pid) {
//            this.id = id;
//            this.name = name;
//            this.pid = pid;
//        }
//
//        public Tree() {
//
//        }
//    }

//    public static void main(String args[]) {
//
//        Set<Tree> set = new HashSet<>();
//        set.add(new Tree("11", "ddd1", null));
//        set.add(new Tree("12", "ddd2", null));
//        set.add(new Tree("13", "ddd3", null));
//
//        set.add(new Tree("111", "ddd1", "11"));
//        set.add(new Tree("112", "ddd2", "11"));
//        set.add(new Tree("113", "ddd3", "11"));
//
//        set.add(new Tree("1111", "ddd1", "111"));
//        set.add(new Tree("1112", "ddd2", "111"));
//
//        set.add(new Tree("121", "ddd1", "12"));
//        set.add(new Tree("122", "ddd2", "12"));
//        set.add(new Tree("123", "ddd3", "12"));
//
//
//        FeatureTreeUtil a = new FeatureTreeUtil(set);
//        System.out.println(JSONObject.toJSONString(set));
//        new ArrayList().add("ddd");
//
//
//        List set1 = new ArrayList();
//        set1.add("1111");
//        System.out.println(JSONObject.toJSONString(a.getAncestors(set1, true)));
//        System.out.println(JSONObject.toJSONString(a.getAncestors(set1, false)));
//
//        List set2 = new ArrayList();
//        set2.add("11");
//        System.out.println(JSONObject.toJSONString(a.getDescendants(set2, false)));
//        System.out.println(JSONObject.toJSONString(a.getDescendants(set2, true)));
//
//    }


}
